#include "Rectangle.h"
#include <QSGRectangleNode>
#include <QSGVertexColorMaterial>
#include "tool.h"

class RectangleItemNode : public QSGRectangleNode
{
public:
    RectangleItemNode() : mGeo(QSGGeometry::defaultAttributes_ColoredPoint2D(), 4)
    {
        QSGGeometry::updateColoredRectGeometry(&mGeo, QRectF());
        setMaterial(&mMaterial);
        setGeometry(&mGeo);
        setColor(QColor(255,255,255));
    }
public:
    virtual void setRect(const QRectF &rect) override
    {
        QSGGeometry::updateColoredRectGeometry(&mGeo, rect);
        markDirty(QSGNode::DirtyGeometry);
    }
    virtual QRectF rect() const override
    {
        auto vertices =  mGeo.vertexDataAsColoredPoint2D();
        return {vertices[0].x,vertices[0].y, vertices[3].x - vertices[0].x, vertices[3].y - vertices[0].y};
    }
    virtual void setColor(const QColor &color) override
    {
        if (color != mColor)
        {
            mColor = color;
            auto vertices =  mGeo.vertexDataAsColoredPoint2D();
            for (int i = 0; i <4; ++i)
            {
                vertices[i].r = uchar(qRound(color.redF() * color.alphaF() * 255));
                vertices[i].g = uchar(qRound(color.greenF() * color.alphaF() * 255));
                vertices[i].b = uchar(qRound(color.blueF() * color.alphaF() * 255));
                vertices[i].a = uchar(qRound(color.alphaF() * 255));
            }
            markDirty(QSGNode::DirtyGeometry);
        }
    }
    virtual QColor color() const override
    {
        return mColor;
    }
private:
    QColor mColor;
    QSGGeometry mGeo;
    QSGVertexColorMaterial mMaterial;
};
RectangleItem::RectangleItem(QQuickItem* parent)
    : Super(parent)
{
    setFlag(Super::ItemHasContents);
    connect(this, &QQuickItem::xChanged, this, [this](){
        mGoemetryChanged = true;
        update();
    });
    connect(this, &QQuickItem::yChanged, this, [this](){
        mGoemetryChanged = true;
        update();
    });
    connect(this, &QQuickItem::widthChanged, this, [this](){
        mGoemetryChanged = true;
        update();
    });
    connect(this, &QQuickItem::heightChanged, this, [this](){
        mGoemetryChanged = true;
        update();
    });
}

RectangleItem::~RectangleItem() { }

QSGNode* RectangleItem::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData* data)
{
    (void)data;
    QSGRectangleNode*     node = nullptr;

    if (!oldNode)
    {
        node = new RectangleItemNode;
    }
    else
    {
        node = static_cast<QSGRectangleNode*>(oldNode);
    }
    node->setColor(color());
    if (mGoemetryChanged)
    {
        mGoemetryChanged = false;
        node->setRect(boundingRect());
    }
    return node;
}

const QColor &RectangleItem::color() const
{
    return mColor;
}

void RectangleItem::setColor(const QColor &newColor)
{
    if (mColor == newColor)
        return;
    mColor = newColor;
    emit colorChanged();
    update();
}
